/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package ticketbooking;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @author Kse7en
 */
public class KeyManagement {
        
        public static KeyPair KeyPairGenerator(int keySize) throws Exception {
                
                KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
                kpg.initialize(keySize);
                KeyPair kp = kpg.genKeyPair();
                PublicKey publicKey = kp.getPublic();
                PrivateKey privateKey = kp.getPrivate();
                return kp;
        }
        
        public static SecretKey PBE(String password, String salt, int keyLength) throws Exception {
                
                SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, keyLength);
                SecretKey tmp = factory.generateSecret(spec);
                SecretKey secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
                return secretKey;
        }
        
        private static void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
                
                ObjectOutputStream oout = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream(fileName)));
                try {
                        oout.writeObject(mod);
                        oout.writeObject(exp);
                } catch (Exception e) {
                        throw new IOException("Unexpected error", e);
                } 
        }
        
        public static void saveKeyPair(KeyPair kp) throws Exception {
                
                KeyFactory fact = KeyFactory.getInstance("RSA");
                RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
                RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);

                saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
                saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());
        }
        
         static PublicKey readPublicKeyFromFile(String fileName) throws IOException {
                
                InputStream in = new FileInputStream(fileName);
                ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
                try {
                        BigInteger m = (BigInteger) oin.readObject();
                        BigInteger e = (BigInteger) oin.readObject();
                        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
                        KeyFactory fact = KeyFactory.getInstance("RSA");
                        PublicKey pubKey = fact.generatePublic(keySpec);
                        return pubKey;
                } catch (Exception e) {
                        throw new RuntimeException("Spurious serialisation error", e);
                } 
        }
        
        static PrivateKey readPrivateKeyFromFile(String fileName) throws IOException {
                
                InputStream in = new FileInputStream(fileName);
                ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
                try {
                        BigInteger m = (BigInteger) oin.readObject();
                        BigInteger e = (BigInteger) oin.readObject();
                        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
                        KeyFactory fact = KeyFactory.getInstance("RSA");
                        PrivateKey privKey = fact.generatePrivate(keySpec);
                        return privKey;
                } catch (Exception e) {
                        throw new RuntimeException("Spurious serialisation error", e);
                } 
        }
        
}
